#!/usr/bin/env node

/**
 * Vhall Stream Saver Native Messaging Host
 * 处理来自 Chrome Extension 的 Native Messaging 请求
 */

const fs = require('fs');
const path = require('path');
const { spawn } = require('child_process');
const os = require('os');

class VhallStreamSaverHost {
  constructor() {
    this.ytDlpPath = this.findYtDlp();
    this.setupMessageHandling();
  }

  /**
   * 查找 yt-dlp 可执行文件
   */
  findYtDlp() {
    const possiblePaths = [
      'yt-dlp',
      '/usr/local/bin/yt-dlp',
      '/usr/bin/yt-dlp',
      path.join(os.homedir(), '.local/bin/yt-dlp'),
      path.join(os.homedir(), 'bin/yt-dlp')
    ];

    for (const ytDlpPath of possiblePaths) {
      try {
        const { execSync } = require('child_process');
        execSync(`${ytDlpPath} --version`, { stdio: 'ignore' });
        return ytDlpPath;
      } catch (error) {
        continue;
      }
    }

    return null;
  }

  // 根据消息中的自定义路径覆盖 yt-dlp 路径
  applyCustomYtDlpPath(data) {
    try {
      const customPath = (data && (data.customYtdlpPath || data.ytdlpPath || data.ytdlp_path)) || null;
      if (!customPath) return;
      if (!fs.existsSync(customPath)) return;

      const { execSync } = require('child_process');
      execSync(`${customPath} --version`, { stdio: 'ignore' });
      this.ytDlpPath = customPath;
    } catch (e) {
      // 无效的自定义路径则忽略，保留原路径或继续自动探测
    }
  }

  /**
   * 设置消息处理
   */
  setupMessageHandling() {
    process.stdin.on('readable', () => {
      const chunks = [];
      let chunk;

      while ((chunk = process.stdin.read()) !== null) {
        chunks.push(chunk);
      }

      if (chunks.length > 0) {
        const input = Buffer.concat(chunks);
        this.handleMessage(input);
      }
    });

    process.stdin.on('end', () => {
      process.exit(0);
    });
  }

  /**
   * 处理来自扩展的消息
   * @param {Buffer} input - 输入数据
   */
  handleMessage(input) {
    try {
      // Native Messaging 协议：前4字节是消息长度
      const messageLength = input.readUInt32LE(0);
      const messageData = input.slice(4, 4 + messageLength).toString();
      const message = JSON.parse(messageData);

      this.processMessage(message);
    } catch (error) {
      this.sendResponse({
        success: false,
        error: `Failed to parse message: ${error.message}`
      });
    }
  }

  /**
   * 处理具体消息
   * @param {Object} message - 消息对象
   */
  async processMessage(message) {
    const { action, data } = message;

    try {
      switch (action) {
      case 'CHECK_YTDLP':
        this.applyCustomYtDlpPath(data || {});
        await this.checkYtDlp();
        break;

      case 'DOWNLOAD_STREAM':
        this.applyCustomYtDlpPath(data || {});
        await this.downloadStream(data);
        break;

      case 'GET_FORMATS':
        this.applyCustomYtDlpPath(data || {});
        await this.getFormats(data);
        break;

      case 'INSTALL_YTDLP':
        await this.installYtDlp();
        break;

      default:
        this.sendResponse({
          success: false,
          error: `Unknown action: ${action}`
        });
      }
    } catch (error) {
      this.sendResponse({
        success: false,
        error: error.message
      });
    }
  }

  /**
   * 检查 yt-dlp 是否可用
   */
  async checkYtDlp() {
    if (!this.ytDlpPath) {
      this.sendResponse({
        success: false,
        available: false,
        error: 'yt-dlp not found'
      });
      return;
    }

    try {
      const { execSync } = require('child_process');
      const version = execSync(`${this.ytDlpPath} --version`, { encoding: 'utf8' }).trim();

      this.sendResponse({
        success: true,
        available: true,
        version: version,
        path: this.ytDlpPath
      });
    } catch (error) {
      this.sendResponse({
        success: false,
        available: false,
        error: error.message
      });
    }
  }

  // 解析命令行参数字符串（支持引号）
  parseArgs(argString) {
    if (!argString || typeof argString !== 'string') return [];
    const args = [];
    let current = '';
    let inQuotes = false;
    let quoteChar = null;
    for (let i = 0; i < argString.length; i++) {
      const ch = argString[i];
      if ((ch === '"' || ch === "'") && !inQuotes) {
        inQuotes = true; quoteChar = ch; continue;
      }
      if (inQuotes && ch === quoteChar) {
        inQuotes = false; quoteChar = null; continue;
      }
      if (!inQuotes && /\s/.test(ch)) {
        if (current.length > 0) { args.push(current); current = ''; }
        continue;
      }
      current += ch;
    }
    if (current.length > 0) args.push(current);
    return args;
  }

  /**
   * 下载流
   * @param {Object} streamData - 流数据
   */
  async downloadStream(streamData) {
    if (!this.ytDlpPath) {
      this.sendResponse({
        success: false,
        error: 'yt-dlp not available'
      });
      return;
    }

    const { url, title, quality, headers, outputPath, ytdlpArgs } = streamData;

    // 构建 yt-dlp 命令参数
    const args = [
      url,
      '--output', outputPath || `${title || 'video'}.%(ext)s`,
      '--format', quality || 'best',
      '--no-playlist'
    ];

    // 追加自定义参数
    if (ytdlpArgs) {
      try {
        args.push(...this.parseArgs(ytdlpArgs));
      } catch (_) { /* 忽略解析失败 */ }
    }

    // 添加请求头
    if (headers) {
      Object.entries(headers).forEach(([key, value]) => {
        args.push('--add-header', `${key}:${value}`);
      });
    }

    try {
      const ytDlpProcess = spawn(this.ytDlpPath, args, {
        stdio: ['pipe', 'pipe', 'pipe']
      });

      let output = '';
      let error = '';

      ytDlpProcess.stdout.on('data', (data) => {
        output += data.toString();

        // 解析进度信息
        const progressMatch = data.toString().match(/(\d+\.?\d*)%/);
        if (progressMatch) {
          this.sendResponse({
            success: true,
            type: 'progress',
            progress: parseFloat(progressMatch[1])
          });
        }
      });

      ytDlpProcess.stderr.on('data', (data) => {
        error += data.toString();
      });

      ytDlpProcess.on('close', (code) => {
        if (code === 0) {
          this.sendResponse({
            success: true,
            type: 'complete',
            output: output
          });
        } else {
          this.sendResponse({
            success: false,
            error: error || `Process exited with code ${code}`
          });
        }
      });

      ytDlpProcess.on('error', (err) => {
        this.sendResponse({
          success: false,
          error: err.message
        });
      });

    } catch (error) {
      this.sendResponse({
        success: false,
        error: error.message
      });
    }
  }

  /**
   * 获取可用格式
   * @param {Object} data - 请求数据
   */
  async getFormats(data) {
    if (!this.ytDlpPath) {
      this.sendResponse({
        success: false,
        error: 'yt-dlp not available'
      });
      return;
    }

    const { url, headers } = data;
    const args = [url, '--list-formats', '--no-playlist'];

    // 添加请求头
    if (headers) {
      Object.entries(headers).forEach(([key, value]) => {
        args.push('--add-header', `${key}:${value}`);
      });
    }

    try {
      const { execSync } = require('child_process');
      const output = execSync(`${this.ytDlpPath} ${args.join(' ')}`, {
        encoding: 'utf8',
        timeout: 30000
      });

      // 解析格式信息
      const formats = this.parseFormats(output);

      this.sendResponse({
        success: true,
        formats: formats
      });
    } catch (error) {
      this.sendResponse({
        success: false,
        error: error.message
      });
    }
  }

  /**
     * 安装 yt-dlp
     */
  async installYtDlp() {
    try {
      const { execSync } = require('child_process');

      // 根据操作系统选择安装方法
      const platform = os.platform();
      let installCommand;

      if (platform === 'darwin') {
        // macOS - 使用 Homebrew
        installCommand = 'brew install yt-dlp';
      } else if (platform === 'linux') {
        // Linux - 使用 pip
        installCommand = 'pip3 install yt-dlp';
      } else if (platform === 'win32') {
        // Windows - 使用 pip
        installCommand = 'pip install yt-dlp';
      } else {
        throw new Error(`Unsupported platform: ${platform}`);
      }

      const output = execSync(installCommand, {
        encoding: 'utf8',
        timeout: 120000 // 2分钟超时
      });

      // 重新查找 yt-dlp
      this.ytDlpPath = this.findYtDlp();

      this.sendResponse({
        success: true,
        installed: this.ytDlpPath !== null,
        output: output,
        path: this.ytDlpPath
      });
    } catch (error) {
      this.sendResponse({
        success: false,
        error: error.message
      });
    }
  }

  /**
   * 解析格式信息
   * @param {string} output - yt-dlp 输出
   */
  parseFormats(output) {
    const formats = [];
    const lines = output.split('\n');

    for (const line of lines) {
      const formatMatch = line.match(/^(\w+)\s+(\w+)\s+(.+?)(?:\s+(\d+x\d+))?(?:\s+(\d+)k)?/);
      if (formatMatch) {
        formats.push({
          format_id: formatMatch[1],
          ext: formatMatch[2],
          description: formatMatch[3].trim(),
          resolution: formatMatch[4] || null,
          bitrate: formatMatch[5] ? parseInt(formatMatch[5]) : null
        });
      }
    }

    return formats;
  }

  /**
     * 发送响应到扩展
     * @param {Object} response - 响应对象
     */
  sendResponse(response) {
    const message = JSON.stringify(response);
    const messageLength = Buffer.byteLength(message);

    // Native Messaging 协议：前4字节是消息长度
    const lengthBuffer = Buffer.allocUnsafe(4);
    lengthBuffer.writeUInt32LE(messageLength, 0);

    process.stdout.write(lengthBuffer);
    process.stdout.write(message);
  }
}

// 启动 Native Host
new VhallStreamSaverHost();
